package br.com.harley.torneio.business;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import org.slf4j.Logger;

import br.com.harley.torneio.constant.MensagemAplicacaoErro;
import br.com.harley.torneio.domain.Usuario;
import br.com.harley.torneio.exception.NegocioException;
import br.com.harley.torneio.persistence.UsuarioDAO;
import br.com.harley.torneio.util.Constantes;
import br.com.harley.torneio.util.SenhaUtil;
import br.com.harley.torneio.validator.ValidadorGenerico;
import br.gov.frameworkdemoiselle.annotation.Name;
import br.gov.frameworkdemoiselle.message.DefaultMessage;
import br.gov.frameworkdemoiselle.message.Message;
import br.gov.frameworkdemoiselle.stereotype.BusinessController;
import br.gov.frameworkdemoiselle.transaction.Transactional;

@Name("usuarioBC")
@BusinessController
public class ManterUsuarioBC extends BaseBC<Usuario, Integer, UsuarioDAO> {

	private static final long serialVersionUID = 1L;

	/**
	 * {@link Logger} da classe.
	 */
	@SuppressWarnings("unused")
	@Inject
	private Logger logger;

	// @Inject
	// private MensagemUtil mensagemUtil;
	//
	// @Inject
	// private ResourceBundle bundle;

	@Inject
	protected ValidadorGenerico validadorGenerico;

	@Inject
	protected SenhaUtil senhaUtil;

	/**
	 * Inclui um novo usuário.
	 * 
	 * @param novoUsuario
	 *            Novo usuário sendo incluído.
	 * @throws NegocioException
	 *             Caso haja erros na validação é lançada exceção de negócio com
	 *             sua lista de mensagens preenchida.
	 */
	@Transactional
	public void incluirUsuario(final Usuario novoUsuario) throws NegocioException {
		validarUsuario(novoUsuario);
		criptografarSenha(novoUsuario);
		getDelegate().insert(novoUsuario);
	}

	/**
	 * Atualiza um usuário existente.
	 * 
	 * @param usuario
	 *            Usuário sendo atualizado.
	 * @throws NegocioException
	 *             Caso haja erros na validação é lançada exceção de negócio com
	 *             sua lista de mensagens preenchida.
	 */
	@Transactional
	public void atualizarUsuario(final Usuario usuario) throws NegocioException {
		validarUsuario(usuario);
		Usuario uTemp = (Usuario) getDelegate().load(usuario.getId());
		String senha = uTemp.getSenha();
		if (!senha.equals(usuario.getSenha())) {
			criptografarSenha(usuario);
			// enviar email ao alterar senha de usuario
		}
		getDelegate().update(usuario);
	}

	/**
	 * Realiza todas as validações necessárias para atualizar ou incluir um novo
	 * usuário.
	 * 
	 * @param usuario
	 *            Usuário sendo incluído ou atualizado.
	 * @throws NegocioException
	 *             Caso haja erros na validação é lançada exceção de negócio com
	 *             sua lista de mensagens preenchida.
	 */
	protected void validarUsuario(Usuario usuario) throws NegocioException {
		List<Message> mensagens = new ArrayList<Message>();
		mensagens.addAll(validarObrigatoriedadeDosCampos(usuario));
		mensagens.addAll(validarFormacaoDosCampos(usuario));
		mensagens.addAll(validarConsistenciaDosCampos(usuario));

		if (!mensagens.isEmpty()) {
			throw new NegocioException("Falha na validação do usuário.", mensagens);
		}
	}

	/**
	 * Valida o preenchimento dos campos obrigatórios.
	 * 
	 * @param usuario
	 *            Usuário sendo validado.
	 * @return Lista contendo mensagens de erro de validação.
	 */
	protected List<Message> validarObrigatoriedadeDosCampos(Usuario usuario) {
		List<Message> msgs = new ArrayList<Message>();
		validadorGenerico.verificarPreenchimentoDoCampo(Constantes.LABELS.LABEL_LOGIN, usuario.getLogin(), msgs);
		validadorGenerico.verificarPreenchimentoDoCampo(Constantes.LABELS.LABEL_CPF, usuario.getCpf(), msgs);
		validadorGenerico.verificarPreenchimentoDoCampo(Constantes.LABELS.LABEL_SENHA, usuario.getSenha(), msgs);
		validadorGenerico.verificarPreenchimentoDoCampo(Constantes.LABELS.LABEL_NOME, usuario.getNome(), msgs);
		validadorGenerico.verificarPreenchimentoDoCampo(Constantes.LABELS.LABEL_EMAIL, usuario.getEmail(), msgs);
		return msgs;
	}

	// protected void verificarPreenchimentoDoCampo(String campo, String valor,
	// List<Message> msgs) {
	// if (!validadorGenerico.foiPreenchido(valor)) {
	// Message msg =
	// mensagemUtil.buscaMensagem(MensagemAplicacaoErro.CAMPO_OBRIGATORIO,
	// bundle.getString(campo));
	// msgs.add(msg);
	// }
	// }

	/**
	 * Valida a formação dos campos.
	 * 
	 * @param usuario
	 *            Usuário sendo validado.
	 * @return Lista contendo mensagens de erro de validação.
	 */
	protected List<Message> validarFormacaoDosCampos(Usuario usuario) {
		List<Message> msgs = new ArrayList<Message>();
		validadorGenerico.validarTamanho(Constantes.LABELS.LABEL_LOGIN, usuario.getLogin(),
				Constantes.TAMANHOS.TAM_MIN_LOGIN, Constantes.TAMANHOS.TAM_MAX_LOGIN, msgs);
		validadorGenerico.validarTamanho(Constantes.LABELS.LABEL_CPF, usuario.getCpf(), Constantes.TAMANHOS.TAM_CPF,
				Constantes.TAMANHOS.TAM_CPF, msgs);
		validadorGenerico.validarTamanho(Constantes.LABELS.LABEL_SENHA, usuario.getSenha(),
				Constantes.TAMANHOS.TAM_MIN_SENHA, Constantes.TAMANHOS.TAM_MAX_SENHA, msgs);
		validadorGenerico.validarTamanho(Constantes.LABELS.LABEL_NOME, usuario.getNome(), null,
				Constantes.TAMANHOS.TAM_MAX_NOME, msgs);
		validadorGenerico.validarTamanho(Constantes.LABELS.LABEL_EMAIL, usuario.getEmail(), null,
				Constantes.TAMANHOS.TAM_MAX_EMAIL, msgs);
		return msgs;
	}

	/**
	 * Valida a consistência dos campos.
	 * 
	 * @param usuario
	 *            Usuário sendo validado.
	 * @return Lista contendo mensagens de erro de validação.
	 */
	protected List<Message> validarConsistenciaDosCampos(Usuario usuario) {
		List<Message> mensagens = new ArrayList<Message>();

		if (usuario.getLogin() != null && existeUsuarioComMesmoLogin(usuario)) {
			Message msg = new DefaultMessage(mensagemUtil.buscaMensagem(MensagemAplicacaoErro.CAMPO_UNICO_DUPLICADO)
					.getText(), bundle.getString(Constantes.LABELS.LABEL_USUARIO),
					bundle.getString(Constantes.LABELS.LABEL_LOGIN));
			mensagens.add(msg);
		}
		if (usuario.getCpf() != null && existeUsuarioComMesmoCpf(usuario)) {
			Message msg = new DefaultMessage(mensagemUtil.buscaMensagem(MensagemAplicacaoErro.CAMPO_UNICO_DUPLICADO)
					.getText(), bundle.getString(Constantes.LABELS.LABEL_USUARIO),
					bundle.getString(Constantes.LABELS.LABEL_CPF));
			mensagens.add(msg);
		}
		if (!senhaEhIgualConfirmacao(usuario)) {
			Message msg = new DefaultMessage(mensagemUtil.buscaMensagem(
					MensagemAplicacaoErro.SENHA_DIFERENTE_CONFIRMACAO).getText());
			mensagens.add(msg);
		}

		return mensagens;
	}

	protected boolean existeUsuarioComMesmoLogin(Usuario usuario) {
		return existeEntidadeComMesmoAtributo(usuario, "login", usuario.getLogin());
	}

	protected boolean existeUsuarioComMesmoCpf(Usuario usuario) {
		return existeEntidadeComMesmoAtributo(usuario, "cpf", usuario.getCpf());
	}

	protected boolean senhaEhIgualConfirmacao(Usuario usuario) {
		if (usuario.getSenha().equals(usuario.getConfirmacaoSenha())) {
			return true;
		} else {
			return false;
		}
	}

	public void criptografarSenha(Usuario usuario) {
		usuario.setSenha(senhaUtil.gerarHash(usuario.getSenha(),
				bundle.getString(Constantes.SENHA.ALGORITMO_CRIPTOGRAFIA)));
	}

	// public void setMensagemUtil(MensagemUtil mensagemUtil) {
	// this.mensagemUtil = mensagemUtil;
	// }
	//
	// public void setBundle(ResourceBundle bundle) {
	// this.bundle = bundle;
	// }

	/**
	 * {@inheritDoc}
	 */
	public void setLogger(Logger logger) {
		this.logger = logger;
	}

	/**
	 * @param validadorGenerico
	 *            the validadorGenerico to set
	 */
	public void setValidadorGenerico(ValidadorGenerico validadorGenerico) {
		this.validadorGenerico = validadorGenerico;
	}

}